﻿using mozhi.smarterp.AuthorCenter.Enums;
using mozhi.smarterp.AuthorCenter.OpenIddict.Repositories;
using mozhi.smarterp.AuthorCenter.Permissions.Groups;
using mozhi.smarterp.AuthorCenter.Permissions.Items;
using mozhi.smarterp.AuthorCenter.Permissions.Repositories;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Clients;
using Volo.Abp.Guids;
using Volo.Abp.Identity;

namespace mozhi.smarterp.AuthorCenter.Permissions
{
    public class PermissionGroupAppService : AuthorCenterAppService, IPermissionGroupAppService
    {
        public IPermissionGroupRepository _repository;
        private IOpenIddictClientTypeRepository _openIddictClientTypeRepository;
        private ICurrentClient _currentClient;
        private IGuidGenerator _guidGenerator;

        public PermissionGroupAppService(IPermissionGroupRepository repository , IOpenIddictClientTypeRepository openIddictClientTypeRepository , ICurrentClient currentClient , IGuidGenerator guidGenerator)
        {
            _repository = repository;
            _openIddictClientTypeRepository = openIddictClientTypeRepository;
            _currentClient = currentClient;
            _guidGenerator = guidGenerator;
        }

        public async Task<PermissionGroupDto> GetAsync(Guid id)
        {
            var group = await _repository.GetAsync(id);

            if (group == null)
                return null;

            var permissTypes = await GetPermissionTypesByClientType();

            if (!permissTypes.Contains(group.Type))
                return null;

            return ObjectMapper.Map<PermissionGroup, PermissionGroupDto>(group);
        }


        public async Task<PagedResultDto<PermissionGroupDto>> GetListAsync(PermissionGroupFilter filter)
        {
            var permissionTypes = await GetPermissionTypesByClientType();

            if (permissionTypes.Count == 0)
                return new PagedResultDto<PermissionGroupDto>();

            if(filter.Type.HasValue && !permissionTypes.Contains(filter.Type.Value))
                return new PagedResultDto<PermissionGroupDto>();

            permissionTypes = filter.Type.HasValue ? new List<PermissionType>() { filter.Type.Value } : permissionTypes;

            var count = await _repository.GetCountAsync(null, permissionTypes);

            var items = await _repository.GetListAsync("Code", filter.MaxResultCount, filter.SkipCount, null, true, permissionTypes);

            var result = new PagedResultDto<PermissionGroupDto>();

            result.Items = ObjectMapper.Map<List<PermissionGroup>, List<PermissionGroupDto>>(items);
            result.TotalCount = count;

            return result;
        }

        public async Task<List<PermissionGroupDto>> CreateAsync(List<PermissionGroupCreateDto> inputs)
        {
            if (inputs == null || inputs.Count == 0)
                throw new ArgumentNullException("inputs");

            var permissionTypes = await GetPermissionTypesByClientType();

            if (inputs.Any(x => !permissionTypes.Contains(x.Type)))
                throw new BusinessException("100000", "非法的Type值，不能创建权限组");

            var permissionGroups = new List<PermissionGroup>();

            foreach (var input in inputs)
            {
                var match = await _repository.FindAsync(x => x.Type == input.Type && x.Code == input.Code);

                if (match != null)
                    throw new UserFriendlyException($"编号：{input.Code}重复", "100000");

                var permissionItems = new List<PermissionItem>();

                if (input.Items != null)
                {
                    foreach (var item in input.Items)
                    {
                        var permissionItem = new PermissionItem(_guidGenerator.Create(), item.ParentId, item.Code, item.Name, input.Type);
                        permissionItems.Add(permissionItem);
                    }
                }

                var permissionGroup = new PermissionGroup(_guidGenerator.Create(), input.Code, input.Name, input.Type);

                permissionGroup.AddItems(permissionItems);

                permissionGroups.Add(permissionGroup);
            }

            await _repository.InsertManyAsync(permissionGroups);

            return ObjectMapper.Map<List<PermissionGroup>, List<PermissionGroupDto>>(permissionGroups);
        }

        public async Task<List<PermissionGroupDto>> UpdateAsync(List<PermissionGroupUpdateDto> inputs)
        {
            if (inputs == null || inputs.Count == 0)
                throw new ArgumentNullException("inputs");

            var permissionTypes = await GetPermissionTypesByClientType();

            if (inputs.Any(x => !permissionTypes.Contains(x.Type)))
                throw new BusinessException("100000", "非法的Type值，不能修改权限组");

            var permissionGroups = new List<PermissionGroup>();

            foreach(var input in inputs)
            {
                var permissionGroup = await _repository.GetAsync(input.Id);

                if (permissionGroup == null)
                    throw new BusinessException("100000", $"权限组：{input.Id}不存在");

                permissionGroups.Add(permissionGroup);

                permissionGroup.ChangeCodeOrName(input.Code , input.Name);

                var permissionItems = new List<PermissionItem>();

                if (input.Items == null || input.Items.Count == 0)
                    continue;

                foreach(var item in input.Items)
                {
                    var itemId = item.Id.HasValue ? item.Id.Value : _guidGenerator.Create();

                    var permissionItem = new PermissionItem(itemId, item.ParentId, item.Code, item.Name, input.Type);

                    permissionItems.Add(permissionItem);
                }

                permissionGroup.AddItems(permissionItems);
            }

            await _repository.UpdateManyAsync(permissionGroups);

            return ObjectMapper.Map<List<PermissionGroup>, List<PermissionGroupDto>>(permissionGroups);
        }

        public async Task DeleteAsync(Guid id)
        {
            var match = _repository.GetAsync(id);

            if(match==null)
                throw new BusinessException("100000", $"权限组：{id}不存在");

            await _repository.DeleteAsync(id);
        }


        public async Task<PermissionItemDto> GetItemAsync(Guid id)
        {
            var item = await _repository.GetItemAsync(id);

            return ObjectMapper.Map<PermissionItem, PermissionItemDto>(item);
        }

        public async Task<PermissionItemDto> CreateItemAsync(PermissionItemCreateDto input)
        {
            var group = await _repository.GetAsync(input.PermissionGroupId);

            if (group == null)
                throw new BusinessException("100000", $"权限组：{input.PermissionGroupId}不存在");

            var permissionTypes = await GetPermissionTypesByClientType();

            if (!permissionTypes.Any(x => x == group.Type))
                throw new BusinessException("100000", "非法的Type值，不能新增权限组");

            var permissionItem = new PermissionItem(_guidGenerator.Create(), input.ParentId, input.Code, input.Name, group.Type);

            group.AddItems(new List<PermissionItem> { permissionItem });

            await _repository.UpdateAsync(group);

            return ObjectMapper.Map<PermissionItem, PermissionItemDto>(permissionItem);

        }

        public async Task<PermissionItemDto> UpdateItemAsync(PermissionItemUpdateDto input)
        {
            var group = await _repository.GetAsync(input.PermissionGroupId);

            if (group == null)
                throw new BusinessException("100000", $"权限组：{input.PermissionGroupId}不存在");

            var permissionTypes = await GetPermissionTypesByClientType();

            if (!permissionTypes.Any(x => x == group.Type))
                throw new BusinessException("100000", "非法的Type值，不能新增权限组");

            var permissionItem = await _repository.GetItemAsync(input.Id);

            if(permissionItem==null)
                throw new BusinessException("100000", $"权限项：{input.PermissionGroupId}不存在");

            permissionItem.ChangeCodeOrName(input.Code , input.Name);
            permissionItem.ChangeParentId(input.ParentId);

            group.AddItems(new List<PermissionItem> { permissionItem });

            await _repository.UpdateAsync(group);

            return ObjectMapper.Map<PermissionItem, PermissionItemDto>(permissionItem);
        }

        public async Task DeleteItemAsync(Guid id)
        {
            var permissionItem = await _repository.GetItemAsync(id);

            if (permissionItem == null)
                throw new BusinessException("100000", $"权限项：{id}不存在");

            var group = await _repository.GetAsync(permissionItem.PermissionGroupId.Value);

            if (group == null)
                throw new BusinessException("100000", $"权限组：{permissionItem.PermissionGroupId}不存在");

            group.RemoveItems(new List<PermissionItem>() { permissionItem });

            await _repository.UpdateAsync(group);
        }


        #region
        private async Task<List<PermissionType>> GetPermissionTypesByClientType()
        {
            var clientId = _currentClient.Id;

            var clientType = (await _openIddictClientTypeRepository.GetListAsync(null, int.MaxValue, 0, clientId)).FirstOrDefault();

            var permissionTypes = GetPermissionTypesByClientType(clientType?.ClientType);

            return permissionTypes;
        }


        private List<PermissionType> GetPermissionTypesByClientType(ClientType? clientType)
        {
            if (clientType == ClientType.PlatformClient)
                return new List<PermissionType>() { PermissionType.PlatformItem, PermissionType.EnterpriseItem };

            if (clientType == ClientType.EnterpriseClient)
                return new List<PermissionType>() { PermissionType.EnterpriseItem };

            return new List<PermissionType>();
        }

       
        #endregion
    }
}
